﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Affirma.ThreeSharp.Wrapper;
using System.Xml;
using System.Text.RegularExpressions;
using System.IO;
using log4net;

namespace CloudDrive.S3
{
    public class FileProxy
    {
        private S3DriveInformation _DriveInfo;
        private List<FileInfo> _Files;
        private ThreeSharpWrapper _ThreeSharpWrapper;
        private ILog _Log;
        public FileProxy(S3DriveInformation driveInfo)
        {
            _ThreeSharpWrapper = new ThreeSharpWrapper(driveInfo.Key, driveInfo.SecretKey);
            _DriveInfo = driveInfo;
            _Files = GetAllFiles();
            _Log = LogManager.GetLogger(typeof(FileProxy));
        }
        public IEnumerable<FileInfo> Files
        {
            get { return _Files; }
        }
        private List<FileInfo> GetAllFiles()
        {
            string xmlResponse = _ThreeSharpWrapper.ListBucket(_DriveInfo.BucketName);
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xmlResponse);
            var documentElement = xmlDoc.DocumentElement;
            XmlNamespaceManager nsManager = new XmlNamespaceManager(xmlDoc.NameTable);
            nsManager.AddNamespace("x", documentElement.NamespaceURI);
            var nav = documentElement.SelectNodes("/x:ListBucketResult/x:Contents", nsManager);
            var files = new List<FileInfo>();
            //files.Add(new FileInfo()
            //{
            //    FullName = "\\",
            //    Length = 0,
            //    LastModified = DateTime.Now
            //});
            foreach (XmlNode node in nav)
            {
                FileInfo info = new FileInfo()
                {
                    FullName = "\\" + node.SelectSingleNode("x:Key", nsManager).InnerText,
                    Length = long.Parse(node.SelectSingleNode("x:Size", nsManager).InnerText),
                    LastModified = DateTime.Parse(node.SelectSingleNode("x:LastModified", nsManager).InnerText)
                };
                files.Add(info);
            }
            return files;
        }
        private bool FileExists(string filename)
        {
            return _Files.Select(x => x.FullName).Contains(filename, StringComparer.CurrentCultureIgnoreCase);                
        }
        private void InsureValidFilename(string filename)
        {
            if (filename.StartsWith("\\"))
                filename = filename.Substring(1);
            var utf8Key = ASCIIEncoding.UTF8.GetBytes(filename);
            if (utf8Key.Length > 128)
                throw new PathTooLongException();
        }
        public FileInfo Create(string filename, System.IO.FileMode mode)
        {
            InsureValidFilename(filename);
            FileInfo file;
            lock (_Files)
            {
                file = _Files.SingleOrDefault(x => x.FullName.Equals(filename, StringComparison.CurrentCultureIgnoreCase));
                if (file == null)
                {
                    if (mode == FileMode.Open
                        || mode == FileMode.Append
                        || mode == FileMode.Truncate)
                        throw new System.IO.FileNotFoundException();

                    _Log.Info(filename + " created");
                    file = new FileInfo()
                    {
                        FullName = filename,
                        LastModified = DateTime.Now,
                        Length = 0
                    };
                    _Files.Add(file);
                }
                else
                {
                    if (mode == FileMode.CreateNew)
                        throw new IOException("File already exists");
                }
                
            }
            return file;
        }
        public FileInfo GetFileInfo(string filename)
        {
            var file = _Files.SingleOrDefault(x => x.FullName.Equals(filename, StringComparison.CurrentCultureIgnoreCase));
            return file;
        }
        public void Delete(string filename)
        {
            var info = GetFileInfo(filename);
            if (info == null)
                throw new FileNotFoundException();
            _Files.Remove(info);
        }
        //public byte[] ReadBytes(string filename, long offset, uint count)
        //{
        //    var file = GetFileInfo(filename);
        //    if (file == null)
        //        throw new FileNotFoundException();
        //    var key = file.FullName;
        //    if (key.StartsWith("\\"))
        //        key = key.Substring(1);
        //    var tempFile = Path.GetTempFileName();
        //    var stream = File.Create(tempFile);
        //    stream.Close();
        //    _ThreeSharpWrapper.GetFileObject(_DriveInfo.BucketName, key, tempFile);
        //    byte[] bytes = File.ReadAllBytes(tempFile);
        //    return bytes;
        //}
        
    }
}
